package org.neu.onlineparadise.controller;

import jakarta.validation.constraints.Pattern;
import org.neu.onlineparadise.Result.Result;
import org.neu.onlineparadise.entity.User;
import org.neu.onlineparadise.service.UserService;
import org.neu.onlineparadise.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/user")
@Validated
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    //注册
    @PostMapping("/register")
    public Result register(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password){
        User user = userService.findByName(username);

        if(user==null){
            userService.register(username, password);
        }else{
            return Result.error("用户名已存在");
        }
        return Result.success();
    }

    //登录只需要验证用户名密码、登录用户信息做缓存即可
    @GetMapping("/login")
    public Result login(@Pattern(regexp = "^\\S{5,16}") String username,@Pattern(regexp = "^\\S{5,16}") String password){
        User loginUser=userService.findByName(username);
        if(loginUser==null){
            return Result.error("用户名有误");
        }
        if(BCryptUtil.checkpw(password,loginUser.getPassword())){   //传入明文密码与用户getPassword方法返回数据
            //储存用户识别信息（ID）
            Map<String,Object> claims=new HashMap<String,Object>();
            claims.put("id",loginUser.getId());
            claims.put("username",loginUser.getUsername());
            //生成token
            String token= JWTutil.genToken(claims);

            //储存到Redis
            ValueOperations<String,String> op=redisTemplate.opsForValue();
            op.set(token,token,1, TimeUnit.HOURS);  //（键，值，过期时间，过期时间单位）

            //登录前准备完成
            return Result.success(token);
        }
        return Result.error("密码错误");
    }

    //发送短信验证码
    @GetMapping("/sendSms")
    public Result sendSms(@Pattern(regexp = "^\\S{11}") String phone) throws Exception {
        //生成验证码
        String code= RandomNumberUtils.getSixBitRandom();
        //发送验证码
        sendSmsUtil sms=new sendSmsUtil(phone,code);
        Map<String,Object> map = new HashMap<>();

        map=sms.SmsUtil();

        if(!"OK".equals(map.get("message"))){
            //验证码发送不成功
            return Result.error("statusCode:"+map.get("statusCode")+";\nmessage:"+map.get("message"));
        }

        //储存验证码
        ValueOperations<String, String> op = redisTemplate.opsForValue();
        op.set(phone,code,5,TimeUnit.MINUTES);  //（键，值，过期时间，过期时间单位）
        return Result.success("验证码发送成功");
    }


    //短信验证码验证接口，成功则登录
    @PostMapping("/smsLogin")
    public Result smsLogin(String phone,String code){
        //从redis中取出缓存的验证码
        ValueOperations<String, String> op = redisTemplate.opsForValue();
        String redisCode=op.get(phone);
        if(redisCode==null){//超时被注销
            return Result.error("验证码无效");
        }

        if(!redisCode.equals(code)){
            return Result.error("验证码错误");
        }
        User user =userService.findByName(phone);

        //原来是否存在该用户
        if(user==null){
            //注册登录操作
            String randomString=RandomNumberUtils.getSixBitRandom();
            userService.register(phone,BCryptUtil.getpw(randomString));
            user=userService.findByName(phone);
        }

        //与登录一致的操作
        Map<String,Object> claims=new HashMap<>();
        claims.put("id",user.getId());
        claims.put("username",user.getUsername());

        String token=JWTutil.genToken(claims);
        ValueOperations<String,String> opsms=redisTemplate.opsForValue();
        opsms.set(token,token,1,TimeUnit.HOURS);

        return Result.success(token);

    }

    //获取用户信息
    @GetMapping("userInfo")
    public Result getUserInfo(){
        Map<String,Object> map= ThreadLocalUtil.get();
        String username= (String) map.get("username");
        User user=userService.findByName(username);
        return Result.success(user);
    }

    //更改用户信息,nickname email
    @PutMapping("updateUserInfo")
    public Result updateUserInfo(User user){
        userService.updateUserInfo(user);
        return Result.success();
    }

    //更改密码 params：原密码、新密码、重复密码  token：用户名、id
    @PatchMapping("/updatePwd")
    public Result updatePwd(Map<String,String> params,@RequestHeader("Authorization") String token){
        String old_pwd=params.get("old_pwd");
        String new_pwd=params.get("new_pwd");
        String re_pwd=params.get("re_pwd");
        if(!StringUtils.hasLength(old_pwd) || !StringUtils.hasLength(new_pwd) || !StringUtils.hasLength(re_pwd)){
            return Result.error("缺少参数");
        }
        if(!new_pwd.equals(re_pwd)){
            return Result.error("两次密码不一致");
        }
        if(!new_pwd.equals(old_pwd)){
            return Result.error("新密码不能与原密码一致");
        }
        Map<String,Object> map=JWTutil.checkToken(token);
        String loginUserName= (String) map.get("username");
        User user=userService.findByName(loginUserName);
        if(!BCryptUtil.checkpw(old_pwd,user.getPassword())){
            return Result.error("原密码错误");
        }
        userService.updatePwd(new_pwd);
        ValueOperations<String,String> op=redisTemplate.opsForValue();
        op.getOperations().delete(token);
        /*
        不重新向Redis中存入token是基于安全性考量，若有需求可以存入
         */

        return Result.success("更改成功");
    }

    //更新用户头像（需要配置阿里云仓库）
    @PatchMapping("/updateAvatar")
    public Result updateAvatar(@RequestParam String avatarURL){
        //使用的是阿里云仓库中存入的图片url
        userService.updateAvatar(avatarURL);
        return Result.success();
    }
}
